<?php
declare(strict_types=1);

namespace App\Service;

use App\Constants\SettleAccessType;
use App\Constants\StrStatus;
use App\Model\Dao\MchAccountDao;
use App\Model\Dao\MchConfigDao;
use App\Model\Dao\MchInfoDao;
use App\Model\Dao\MchSysAdminDao;
use App\Model\Dao\RateSettleDao;
use App\Model\Enum\CommonReviewStatusEnum;
use App\Model\Enum\TradeTransTypeEnum;
use App\Utils\CustomUtils;
use Hyperf\Di\Annotation\Inject;
use App\Model\Dao\TradeTransDao;
use App\Exception\XZXValidationException;
use App\Constants\XZXResponseCode;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Utils\Coroutine;
use App\Utils\DateUtils;
use App\Service\CommonService;

class TradeTransService
{
    /**
     * @Inject()
     * @var TradeTransDao
     */
    private $TradeTranDao;

    /**
     * @Inject()
     * @var MchInfoDao
     */
    private $MchInfoDao;

    /**
     * @Inject()
     * @var MchConfigDao
     */
    private $MchConfigDao;

    /**
     * @Inject()
     * @var RateSettleDao
     */
    private $RateSettleDao;

    /**
     * @Inject()
     * @var MchSysAdminDao
     */
    private $MchSysAdminDao;

    /**
     * @Inject()
     * @var MchAccountDao
     */
    private $MchAccountDao;

    /**
     * @Inject()
     * @var CommonService
     */
    private $CommonService;

    /**
     * @Inject()
     * @var SettleService
     */
    private $SettleService;

    /**
     * @Inject()
     * @var RateCustomizedService
     */
    private $RateCustomizedService;

    public function get($param)
    {
        $result = $this->TradeTranDao->get($param['id']);
        if (!$result) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::DATA_NOT_FOUND));
        }
        if($param['source'] == 2 && !$param['isSuperRole']){
            if(!in_array($result['mchId'],$param['mchIdList'])){
                throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NO_PERMISSION_TO_OPERATE));
            }
        }

        if($param['source'] == 1){
            if($result['mchId'] != $param['mchId']){
                throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NO_PERMISSION_TO_OPERATE));
            }
        }
        if(isset($result['createTime'])){
            $result['createTime'] = DateUtils::getDateTime($result['createTime']);
        }

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$result);
    }

    public function add($param)
    {
        // 验证google secret
        if(!config("isDev")) {
            $mchSysAdmin = $this->MchSysAdminDao->get($param['uid']);
            $this->CommonService->checkGoogleCode($mchSysAdmin['googleAuthSecret'], $param['code']);
        }

        // 查商户，查结算币种，账户
        $mchInfo = $this->MchInfoDao->get($param['mchId']);
        $mchConfig = $this->MchConfigDao->getByMchId($param['mchId']);
        $rateSettle = $this->RateSettleDao->get($mchConfig['settleRateId']);
        $mchAccount = $this->MchAccountDao->getByMchId($param['mchId']);
        $isTrans = $this->TradeTranDao->getLastByMchId($param['mchId']);

        if (empty($mchConfig)) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::NOT_SET_MCH_CONFIG));
        }
        if ($mchInfo['status'] != 1) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::MCH_IS_FORBIDDEN));
        }
        if ($isTrans && ($isTrans['handleStatus'] == 0 || $isTrans['handleStatus'] == 1)) {
            if ($param['type'] == $isTrans['type']){
                throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::TRANSING_ORDER));
            }            
        }
        if ($mchAccount['tradeCashAmount'] < $param['transAmount']) {
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::INSUFFICIENT_BALANCE));
        }
        if ($param['type'] == 1 &&
            ($param['transAmount']) > $rateSettle['maxWithdrawAmount'] || $param['transAmount'] < $rateSettle['minWithdrawAmount']) {
            throw new XZXValidationException("提现金额应在" . ($rateSettle['minWithdrawAmount'] / 100) ."-" . ($rateSettle['maxWithdrawAmount'] / 100));
        }
        if ($param['type'] == 2 &&
            ($param['transAmount']) > $rateSettle['maxTransAmount'] || $param['transAmount'] < $rateSettle['minTransAmount']) {
            throw new XZXValidationException("转账金额应在" . ($rateSettle['maxTransAmount'] / 100) . "-" . ($rateSettle['maxTransAmount'] / 100));
        }
        if ($param['type'] == 1) {
            $param['bankAccountName'] = $mchInfo['bankAccountName'];
            $param['bankAccountNo'] = $mchInfo['bankAccountNo'];
            $param['bankOpenBankNo'] = $mchInfo['bankOpenBankNo'];
        }

        $data            =  [
            'id'                => CustomUtils::createUUID(),
            'mchId'             => $param['mchId'],
            'mchNo'             => $mchInfo['mchNo'],
            'mchEmail'          => $mchInfo['email'],
            'type'              => $param['type'],
            'transNo'           => CustomUtils::createTradeNo('trans'),
            'extraType'         => isset($param['extraType']) ? $param['extraType'] : 0,
            'transAmount'       => $param['transAmount'],
            'transCurrency'     => $mchConfig['settleCurrency'],
            'targetCurrency'    => $param['targetCurrency'],
            'bankAccountName'   => isset($param['bankAccountName']) ? $param['bankAccountName'] : '',
            'bankAccountNo'     => isset($param['bankAccountNo']) ? $param['bankAccountNo'] : '',
            'bankOpenBankNo'    => isset($param['bankOpenBankNo']) ? $param['bankOpenBankNo'] : '',
            'createBy'          => $param['createBy'],
            'createTime'        => time(),
            'createRemark'      => isset($mchInfo['createRemark']) ? $mchInfo['createRemark'] : '',
        ];

        // 转换币种
        $transResult = $this->RateCustomizedService->getTransRateAndAmount([
            'mchId'             => $param['mchId'],
            'sourceCurrency'    => $param['sourceCurrency'],
            'amount'            => $param['transAmount'],
            'targetCurrency'    => $param['targetCurrency'],
            'type'              => $param['type']
        ]);
        $data['targetAmount'] = $transResult['data']['transAmount'];
        if ($param['type'] == 1) {
            // 提现
            $data['transFee'] = $rateSettle['withdrawPerFee'];
        } else {
            // 转账
            $data['transFee'] = $rateSettle['transPerFee'];
            if ($param['extraType'] == 2) {
                $targetMchInfo = $this->MchInfoDao->getByEmail($param['targetMchEmail']);
                if (!$targetMchInfo || $targetMchInfo['status'] != 1) {
                    throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::MCH_IS_FORBIDDEN));
                }
                $data['targetMchId'] = $targetMchInfo['id'];
                $data['targetMchNo'] = $targetMchInfo['mchNo'];
                $data['targetMchEmail'] = $param['targetMchEmail'];
            }
        }

        try {
            $this->TradeTranDao->insert($data);
        } catch (\Throwable $th) {
            CustomUtils::xzxDebug($th);
            throw new XZXValidationException(XZXResponseCode::getMessage(XZXResponseCode::ADD_FAIL));
        }

        // 写队列，提现、转账单结算
        if ($data['type'] == 1) {
            $this->SettleService->addMq($data['mchId'], [
                "accessType"    => SettleAccessType::ACCESS_TYPE_WITHDRAW,
                "withdrawId"    => $data['id'],
                "handleStatus"  => 0
            ]);
        } else {
            $this->SettleService->addMq($data['mchId'], [
                "accessType"    => SettleAccessType::ACCESS_TYPE_TRANS,
                "transId"       => $data['id'],
                "handleStatus"  => 0
            ]);
        }

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),CustomUtils::xzxEmptyObject());
    }

    public function list(array $param)
    {

        $limit = $param['limit'];
        $page = $param['page'];

        $total = $this->TradeTranDao->getCount($param);
        $list = $this->TradeTranDao->getList($param, $page, $limit);

        foreach ($list as $k => $v) {
            (isset($v['createTime']) && !empty($v['createTime'])) && $v['createTime'] = DateUtils::getDateTime($v['createTime']);
            $v['strType'] = TradeTransTypeEnum::getLabel($v['type']);
            $v['strReviewStatus'] = CommonReviewStatusEnum::getLabel($v['reviewStatus']);
            $v['strReReviewStatus'] = CommonReviewStatusEnum::getLabel($v['reReviewStatus']);
            $list[$k] = $v;
        }

        $data = array(
            'total' => $total,
            'list' => $list
        );

        return CustomUtils::xeServiceReturnData(XZXResponseCode::SUCCESS_CODE,XZXResponseCode::getMessage(XZXResponseCode::SUCCESS_CODE),$data);
    }


}
